Skip to contentMethod: AbstractListIterator(ListDescriptor, StorageConnector)
1: /**
2: * Copyright (C) 2019 Czech Technical University in Prague
3: *
4: * This program is free software: you can redistribute it and/or modify it under
5: * the terms of the GNU General Public License as published by the Free Software
6: * Foundation, either version 3 of the License, or (at your option) any
7: * later version.
8: *
9: * This program is distributed in the hope that it will be useful, but WITHOUT
10: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12: * details. You should have received a copy of the GNU General Public License
13: * along with this program. If not, see <http://www.gnu.org/licenses/>.
14: */
15: package cz.cvut.kbss.ontodriver.jena.list;
16:
17: import cz.cvut.kbss.ontodriver.descriptor.ListDescriptor;
18: import cz.cvut.kbss.ontodriver.exception.IntegrityConstraintViolatedException;
19: import cz.cvut.kbss.ontodriver.jena.connector.StorageConnector;
20: import cz.cvut.kbss.ontodriver.jena.exception.ListProcessingException;
21: import cz.cvut.kbss.ontodriver.model.Axiom;
22: import cz.cvut.kbss.ontodriver.model.NamedResource;
23: import org.apache.jena.rdf.model.Property;
24: import org.apache.jena.rdf.model.RDFNode;
25: import org.apache.jena.rdf.model.Resource;
26: import org.apache.jena.rdf.model.Statement;
27:
28: import java.util.Collection;
29: import java.util.NoSuchElementException;
30:
31: import static org.apache.jena.rdf.model.ResourceFactory.createProperty;
32: import static org.apache.jena.rdf.model.ResourceFactory.createResource;
33:
34: abstract class AbstractListIterator {
35:
36: final StorageConnector connector;
37:
38: final Property hasListProperty;
39: final Property hasNextProperty;
40:
41: final String context;
42:
43: int index;
44: private boolean removed = false;
45:
46: Resource previousNode;
47: Resource currentNode;
48: Collection<Statement> cursor;
49:
50: AbstractListIterator(ListDescriptor descriptor, StorageConnector connector) {
51: this.hasListProperty = createProperty(descriptor.getListProperty().getIdentifier().toString());
52: this.hasNextProperty = createProperty(descriptor.getNextNode().getIdentifier().toString());
53:• this.context = descriptor.getContext() != null ? descriptor.getContext().toString() : null;
54: this.connector = connector;
55: this.index = -1;
56: this.currentNode = createResource(descriptor.getListOwner().getIdentifier().toString());
57: moveCursor(currentNode);
58: }
59:
60: void moveCursor(Resource from) {
61: this.cursor = connector.find(from, first() ? hasListProperty : hasNextProperty, null, context);
62: }
63:
64: void resolveNextListNode() {
65: verifySuccessorCount();
66: final RDFNode node = cursor.iterator().next().getObject();
67: if (!node.isURIResource()) {
68: throw new ListProcessingException("Expected successor of node " + currentNode + " to be a named resource.");
69: }
70: final Resource item = node.asResource();
71: index++;
72: this.removed = false;
73: this.previousNode = currentNode;
74: this.currentNode = item;
75: moveCursor(currentNode);
76: }
77:
78: boolean first() {
79: return index == -1;
80: }
81:
82: boolean hasNext() {
83: return !cursor.isEmpty();
84: }
85:
86: void verifySuccessorCount() {
87: if (!hasNext()) {
88: throw new NoSuchElementException("No more elements available.");
89: }
90: if (cursor.size() > 1) {
91: throw new IntegrityConstraintViolatedException(
92: "Encountered multiple successors of list node " + currentNode.getURI());
93: }
94: }
95:
96: void remove(Resource subject, Property property, RDFNode object) {
97: connector.remove(subject, property, object, context);
98: }
99:
100: abstract Axiom<NamedResource> nextAxiom();
101:
102: abstract NamedResource nextValue();
103:
104: /**
105: * Only returns current node.
106: * <p>
107: * Does not advance the iterator like {@link #nextAxiom()} and {@link #nextValue()} do.
108: *
109: * @return Current list node
110: */
111: Resource getCurrentNode() {
112: return currentNode;
113: }
114:
115: /**
116: * Removes the current node without reconnecting the subsequent nodes to the previous one.
117: */
118: void removeWithoutReconnect() {
119: if (first()) {
120: throw new IllegalStateException("Cannot call remove before calling next.");
121: }
122: if (removed) {
123: throw new IllegalStateException("Cannot call remove multiple times on one element.");
124: }
125: assert previousNode != null;
126: assert currentNode != null;
127: remove(previousNode, index == 0 ? hasListProperty : hasNextProperty, currentNode);
128: this.removed = true;
129: }
130:
131: abstract void replace(Resource replacement);
132: }